package cn.attackme.myuploader.service;

import cn.attackme.myuploader.config.UploadConfig;
import cn.attackme.myuploader.model.ExcelContent;
import cn.attackme.myuploader.model.File;
import cn.attackme.myuploader.model.Img;
import cn.attackme.myuploader.utils.FileUtils;

import cn.attackme.myuploader.utils.OCR;
import com.alibaba.fastjson.JSON;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.CellStyle;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import static cn.attackme.myuploader.utils.FileUtils.generateFileName;
import static cn.attackme.myuploader.utils.UploadUtils.*;

/**
 * 文件上传服务
 */
@Service
public class FileService {
    @Value("${server.port}")
    private String port;
    @Value("${server.myip}")
    private String myip;

    /**
     * 上传文件
     * @param md5
     * @param file
     */
    public void upload(String name,
                       String md5,
                       MultipartFile file) throws IOException {
        String path = UploadConfig.path + generateFileName();
        FileUtils.write(path, file.getInputStream());
    }

    public List<ExcelContent> uploadZIP(String httpurl,MultipartFile file){
        List<ExcelContent> excelContentlist = new ArrayList<>();
        String uuid = generateFileName();
        String realpath = uuid + ".zip";
        String path = UploadConfig.path + realpath;
        try {
            String zippath = FileUtils.uploadFile(path, file.getBytes());
            zipUncompress(zippath);
            excelContentlist = readFiles(httpurl,zippath.replace(".zip", ""));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return excelContentlist;
    }
    public Img uploadImg(String name,
                       MultipartFile file) {
        Img img = new Img();
        String uuid = generateFileName();
        String realpath = uuid + ".png";
        String path = UploadConfig.path + realpath;
        try {
            String myurl = "http://"+myip+":"+port;
            img = FileUtils.write(path, file.getInputStream());
            img.setUuid(uuid);
            img.setFilename(name);
            img.setUrl(myurl+"/"+realpath);
            //img.setUrl("http://202.4.130.28:12345/news/2021-4-20/31feb067-93ea-4793-a3a4-96bb0625960f.png");
            //fileDao.save(new File(name, "", path, new Date()));
            return img;
        }catch (IOException e){
            return null;
        }
    }
    //增值税发票pdf上传
    public ExcelContent uploadPDF(MultipartFile file){
        try {
            //优先识别内容
            return FileUtils.getExcelContentByContent(file);
        } catch (Exception e) {
            //识别失败再识别位置
            try {
                return FileUtils.getExcelContentByLocation(file);
            } catch (IOException ioException) {
                //否则为空
                return new ExcelContent();
            }
        }
    }

    //非税票据pdf上传
    public ExcelContent uploadPDF2(MultipartFile file){
        try {
            //优先识别内容
            return FileUtils.getExcelContentByContent2(file);
        } catch (Exception e) {
            //否则为空
            return new ExcelContent();

        }
    }

    /**
     * 分块上传文件
     * @param md5
     * @param size
     * @param chunks
     * @param chunk
     * @param file
     * @throws IOException
     */
    public void uploadWithBlock(String name,
                                String md5,
                                Long size,
                                Integer chunks,
                                Integer chunk,
                                MultipartFile file) throws IOException {
        String fileName = getFileName(md5, chunks);
        FileUtils.writeWithBlok(UploadConfig.path + fileName, size, file.getInputStream(), file.getSize(), chunks, chunk);
        addChunk(md5,chunk);
        if (isUploaded(md5)) {
            removeKey(md5);
            //fileDao.save(new File(name, md5,UploadConfig.path + fileName, new Date()));
        }
    }

    /**
     * 检查Md5判断文件是否已上传
     * @param md5
     * @return
     */
    public boolean checkMd5(String md5) {
        File file = new File();
        file.setMd5(md5);
        return false;
        //return fileDao.getByFile(file) == null;
    }

    public String SaveToExcel(List<ExcelContent> excelContents) {
        String xlsurl = "";
        String xlsTemplate = "电子发票识别结果.xls";
        try {
            String uuid = generateFileName();
            java.io.File dir = new java.io.File(UploadConfig.path+uuid);
            if (!dir.exists()) {// 判断目录是否存在
                dir.mkdir();
            }
            String realpath = uuid + java.io.File.separator + xlsTemplate;
            String oldpath = UploadConfig.path + java.io.File.separator + "template" + java.io.File.separator +xlsTemplate;
            String path = UploadConfig.path + realpath;

            FileInputStream excelFileInputStream = new FileInputStream(oldpath);
            HSSFWorkbook workbook = new HSSFWorkbook (excelFileInputStream);
            excelFileInputStream.close();
            HSSFSheet sheet = workbook.getSheetAt(0);
            //设置红色字体
            HSSFFont hssfFont = workbook.createFont();
            hssfFont.setColor(HSSFFont.COLOR_RED);
            CellStyle cellStyle = workbook.createCellStyle();
            cellStyle.setFont(hssfFont);
            for (int i = 0; i < excelContents.size(); i++) {
                HSSFRow row = sheet.createRow(i+1);
                row.createCell(0).setCellValue(excelContents.get(i).getCode());
                row.createCell(1).setCellValue(excelContents.get(i).getNum());
                row.createCell(2).setCellValue(excelContents.get(i).getTime());
                row.createCell(3).setCellValue(excelContents.get(i).getCheck());
                row.createCell(4).setCellValue(excelContents.get(i).getName());
                if(excelContents.get(i).getPrice()==null || excelContents.get(i).getPrice().isEmpty()){
                    HSSFCell hssfCell = row.createCell(5);
                    hssfCell.setCellValue(-1);
                    hssfCell.setCellStyle(cellStyle);
                }else row.createCell(5).setCellValue(Double.parseDouble(excelContents.get(i).getPrice()));
                if(excelContents.get(i).getTax()==null || excelContents.get(i).getTax().isEmpty()){
                    HSSFCell hssfCell = row.createCell(6);
                    hssfCell.setCellValue(-1);
                    hssfCell.setCellStyle(cellStyle);
                }else row.createCell(6).setCellValue(Double.parseDouble(excelContents.get(i).getTax()));
                if(excelContents.get(i).getSum()==null || excelContents.get(i).getSum().isEmpty()){
                    HSSFCell hssfCell = row.createCell(7);
                    hssfCell.setCellValue(-1);
                    hssfCell.setCellStyle(cellStyle);
                }else row.createCell(7).setCellValue(Double.parseDouble(excelContents.get(i).getSum()));
                row.createCell(8).setCellValue(excelContents.get(i).getFilename());
            }
            java.io.File savefile = new java.io.File(path);
            FileOutputStream output_file =new FileOutputStream(savefile);
            workbook.write(output_file);
            workbook.close();
            output_file.close();

            xlsurl = "http://" + myip + ":" + port + "/" + realpath;


        } catch (Exception e) {
            e.printStackTrace();
        }
        return xlsurl;
    }

    public void zipUncompress(String inputFile) throws Exception {
        java.io.File srcFile = new java.io.File(inputFile);
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new Exception(srcFile.getPath() + "所指文件不存在");
        }
        String destDirPath = inputFile.replace(".zip", "");
        //创建压缩文件对象
        ZipFile zipFile = new ZipFile(srcFile);
        //开始解压
        Enumeration<?> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            // 如果是文件夹，就创建个文件夹
            if (entry.isDirectory()) {
                srcFile.mkdirs();
            } else {
                // 如果是文件，就先创建一个文件，然后用io流把内容copy过去
                java.io.File targetFile = new java.io.File(destDirPath + "/" + entry.getName());
                // 保证这个文件的父文件夹必须要存在
                if (!targetFile.getParentFile().exists()) {
                    targetFile.getParentFile().mkdirs();
                }
                targetFile.createNewFile();
                // 将压缩文件内容写入到这个文件中
                InputStream is = zipFile.getInputStream(entry);
                FileOutputStream fos = new FileOutputStream(targetFile);
                int len;
                byte[] buf = new byte[1024];
                while ((len = is.read(buf)) != -1) {
                    fos.write(buf, 0, len);
                }
                // 关流顺序，先打开的后关闭
                fos.close();
                is.close();
            }
        }
    }

    public List<ExcelContent> readFiles(String httpurl,String inputFile) throws Exception {
        java.io.File srcFile = new java.io.File(inputFile);
        List<ExcelContent> excelContentList = new ArrayList<>();
        if (srcFile.isDirectory()) {
            java.io.File next[] = srcFile.listFiles();
            for (int i = 0; i < next.length; i++) {
                String filename = next[i].getName();
                Img finalimg = null;
                if(!next[i].isDirectory()){
                    if(filename.endsWith(".pdf")||filename.endsWith(".PDF")){
                        FileInputStream fileInputStream=new FileInputStream(next[i]);
                        try {
                            //创建PdfDocument实例
                            PdfDocument doc = new PdfDocument();
                            //加载PDF文件
                            doc.loadFromStream(fileInputStream);
                            //选择pdf第一页
                            PdfPageBase pdfPageBase = doc.getPages().get(0);

                            //识别发票代码
                            Rectangle code_rect = new Rectangle(420, 10, 116, 20);
                            String codeContent = pdfPageBase.extractText(code_rect).replaceAll(" ","").replaceAll("　","");
                            //识别区域正则匹配
                            String p_code = "\\d{12}";
                            Pattern r_code = Pattern.compile(p_code);
                            Matcher m_code = r_code.matcher(codeContent);
                            String code = "";
                            if(m_code.find()) code = m_code.group();

                            //识别发票号码
                            Rectangle num_rect = new Rectangle(413, 34, 117, 18);
                            String numContent = pdfPageBase.extractText(num_rect).replaceAll(" ","").replaceAll("　","");
                            String p_num = "(\\d{8})";
                            Pattern r_num = Pattern.compile(p_num);
                            Matcher m_num = r_num.matcher(numContent);
                            String num = "";
                            if(m_num.find()) num = m_num.group();

                            //发票日期
                            Rectangle time_rect = new Rectangle(413, 47, 129, 20);
                            String timeContent = pdfPageBase.extractText(time_rect).replaceAll(" ","").replaceAll("　","").replaceAll("年","").replaceAll("月","").replaceAll("日","");
                            String p_time = "([0-9]{8})";
                            Pattern r_time = Pattern.compile(p_time);
                            Matcher m_time = r_time.matcher(timeContent);
                            String time = "";
                            if(m_time.find()) {
                                time = m_time.group();
                                time = time.substring(0, 4) + "/" + time.substring(4, 6) + "/" + time.substring(6);
                            }

                            //校验码
                            Rectangle check_rect = new Rectangle(413, 64, 170, 18);
                            String checkContent = pdfPageBase.extractText(check_rect).replaceAll(" ","").replaceAll("　","");
                            String p_check = "(\\d{20})";
                            Pattern r_check = Pattern.compile(p_check);
                            Matcher m_check = r_check.matcher(checkContent);
                            String check = "";
                            if(m_check.find()) check = m_check.group();

                            //开票方名称
                            Rectangle name_rect = new Rectangle(35, 294, 290, 17);
                            String nameContent = pdfPageBase.extractText(name_rect).replaceAll(" ","").replaceAll("　","").replace("名称:","").replace("名称：","");
                            String p_name = "([\\u4E00-\\u9FA5]+|[a-z]+|[A-Z]+)";
                            Pattern r_name = Pattern.compile(p_name);
                            Matcher m_name = r_name.matcher(nameContent);
                            String name = "";
                            if(m_name.find()) name = m_name.group();

                            //金额
                            Rectangle price_rect = new Rectangle(385, 253, 95, 23);
                            String priceContent = pdfPageBase.extractText(price_rect).replaceAll(" ","").replaceAll("　","");
                            String p_price = "(\\d+\\.\\d+)";
                            Pattern r_price = Pattern.compile(p_price);
                            Matcher m_price = r_price.matcher(priceContent);
                            String price = "0";
                            if(m_price.find()) price = m_price.group();

                            //税额
                            Rectangle tax_rect = new Rectangle(499, 252, 86, 23);
                            String taxContent = pdfPageBase.extractText(tax_rect).replaceAll(" ","").replaceAll("　","");
                            String p_tax = "(\\d+\\.\\d+)";
                            Pattern r_tax = Pattern.compile(p_tax);
                            Matcher m_tax = r_tax.matcher(taxContent);
                            String tax = "0";
                            if(m_tax.find()) tax = m_tax.group();

                            //总价
                            Rectangle sum_rect = new Rectangle(433, 274, 150, 20);
                            String sumContent = pdfPageBase.extractText(sum_rect).replaceAll(" ","").replaceAll("　","");
                            String p_sum = "(\\d+\\.\\d+)";
                            Pattern r_sum = Pattern.compile(p_sum);
                            Matcher m_sum = r_sum.matcher(sumContent);
                            String sum = "0";
                            if(m_sum.find()) sum = m_sum.group();

                            ExcelContent excelContent = new ExcelContent(code,num,time,check,name,price,tax,sum);
                            if(excelContent.getCheck().length()>=6) excelContent.setCheck(excelContent.getCheck().substring(excelContent.getCheck().length()-6));
                            excelContent.setFilename(filename);
                            excelContentList.add(excelContent);
                        } catch (Exception e) {
                            return null;
                        }
                    }else{
                        Img img = new Img();
                        String uuid = generateFileName();
                        String realpath = uuid + ".png";
                        String path = UploadConfig.path + realpath;
                        try {
                            String myurl = "http://"+myip+":"+port;
                            FileInputStream fileInputStream=new FileInputStream(next[i]);
                            img = FileUtils.write(path, fileInputStream);
                            img.setUuid(uuid);
                            img.setFilename(filename);
                            img.setUrl(myurl+"/"+realpath);
                            //fileDao.save(new File(filename, "", path, new Date()));
                            finalimg =  img;
                            ExcelContent excelContent = OCR.getResult(httpurl, JSON.toJSONString(finalimg));
                            if(excelContent!=null) {
                                if(excelContent.getCheck().length()>=6) excelContent.setCheck(excelContent.getCheck().substring(excelContent.getCheck().length()-6));
                                excelContent.setFilename(finalimg.getFilename());
                                excelContentList.add(excelContent);
                            }
                        }catch (IOException e){
                        }
                    }
                }
            }
        }
        return excelContentList;
    }
}
